---
id: gradle-plugin-usage
title: Gradle Plugin Usage
sidebar_label: Usage
---


import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

## Downloading Schema SDL

GraphQL endpoints are often public and as such many servers might disable introspection queries in production environment.
Since GraphQL schema is needed to generate type safe clients, as alternative GraphQL servers might expose private
endpoints (e.g. accessible only from within network, etc) that could be used to download schema in Schema Definition
Language (SDL) directly. `graphqlDownloadSDL` task requires target GraphQL server `endpoint` to be specified and can
be executed directly from the command line by explicitly passing `endpoint` parameter

```shell script
$ gradle graphqlDownloadSDL --endpoint="http://localhost:8080/sdl"
```

Task can also be explicitly configured in your Gradle build file

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
}>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLDownloadSDLTask

val graphqlDownloadSDL by tasks.getting(GraphQLDownloadSDLTask::class) {
    endpoint.set("http://localhost:8080/sdl")
}
```

</TabItem>
<TabItem value="groovy">

```groovy
//build.gradle
graphqlDownloadSDL {
    endpoint = "http://localhost:8080/sdl"
}
```

</TabItem>
</Tabs>

:::info
This task does not automatically configure itself to be part of your build lifecycle. You will need to explicitly
invoke it OR configure it as a dependency of some other task.
:::

## Introspecting Schema

Introspection task requires target GraphQL server `endpoint` to be specified. Task can be executed directly from the
command line by explicitly passing endpoint parameter

```shell script
$ gradle graphqlIntrospectSchema --endpoint="http://localhost:8080/graphql"
```

Task can also be explicitly configured in your Gradle build file

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
}>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask

val graphqlIntrospectSchema by tasks.getting(GraphQLIntrospectSchemaTask::class) {
    endpoint.set("http://localhost:8080/graphql")
}
```

</TabItem>
<TabItem value="groovy">

```groovy
//build.gradle
graphqlIntrospectSchema {
    endpoint = "http://localhost:8080/graphql"
}
```

</TabItem>
</Tabs>

:::info
This task does not automatically configure itself to be part of your build lifecycle. You will need to explicitly
invoke it OR configure it as a dependency of some other task.
:::

## Generating Client

GraphQL Kotlin client code is generated based on the provided queries that will be executed against target GraphQL `schemaFile`.
Separate class is generated for each provided GraphQL query and are saved under specified `packageName`.

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
}>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask

val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
  packageName.set("com.example.generated")
  schemaFile.set(file("${project.projectDir}/mySchema.graphql"))
}
```

</TabItem>
<TabItem value="groovy">

```groovy
//build.gradle
graphqlGenerateClient {
    packageName = "com.example.generated"
    schemaFile = file("${project.projectDir}/mySchema.graphql")
}
```

</TabItem>
</Tabs>

This will process all GraphQL files located under `src/main/resources` and generate corresponding GraphQL Kotlin client
data models. Generated classes will be automatically added to the project compile sources.

## Generating Client with Custom Scalars

By default, all custom GraphQL scalars will be serialized as Strings. You can override this default behavior by specifying
custom [scalar converter](https://github.com/ExpediaGroup/graphql-kotlin/blob/master/clients/graphql-kotlin-client/src/main/kotlin/com/expediagroup/graphql/client/converter/ScalarConverter.kt).

For example given following custom scalar in our GraphQL schema

```graphql
scalar UUID
```

We can create a custom converter to automatically convert this custom scalar to `java.util.UUID`

```kotlin
package com.example

import com.expediagroup.graphql.client.converter.ScalarConverter
import java.util.UUID

class UUIDScalarConverter : ScalarConverter<UUID> {
    override fun toScalar(rawValue: Any): UUID = UUID.fromString(rawValue.toString()
    override fun toJson(value: UUID): String = value.toString()
}
```

Afterwards we need to configure our plugin to use this custom converter

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
  }>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.config.GraphQLScalar
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask

val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
  packageName.set("com.example.generated")
  schemaFile.set(file("${project.projectDir}/mySchema.graphql"))
  customScalars.add(GraphQLScalar("UUID", "java.util.UUID", "com.example.UUIDScalarConverter"))
}
```

</TabItem>
<TabItem value="groovy">

```groovy
//build.gradle
import com.expediagroup.graphql.plugin.gradle.config.GraphQLScalar

graphqlGenerateClient {
    packageName = "com.example.generated"
    schemaFile = file("${project.projectDir}/mySchema.graphql")
    customScalars.add(new GraphQLScalar("UUID", "java.util.UUID", "com.example.UUIDScalarConverter"))
}
```

</TabItem>
</Tabs>

## Generating Client using Kotlinx Serialization

GraphQL Kotlin plugins default to generate client data models that are compatible with [Jackson](https://github.com/FasterXML/jackson).
We can change this default behavior by explicitly specifying serializer type (in the extension or explicitly in the generate
client task) and configuring `kotlinx.serialization` compiler plugin. See [kotlinx.serialization documentation](https://github.com/Kotlin/kotlinx.serialization)
for details.

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
  }>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.config.GraphQLScalar
import com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializer

plugins {
    kotlin("plugin.serialization") version $kotlinVersion
}

val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
  packageName.set("com.example.generated")
  schemaFile.set(file("${project.projectDir}/mySchema.graphql"))
  serializer.set(GraphQLSerializer.KOTLINX)
}
```

</TabItem>
<TabItem value="groovy">

```groovy
//build.gradle
import com.expediagroup.graphql.plugin.gradle.config.GraphQLScalar
import com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializer

plugins {
    id 'org.jetbrains.kotlin.plugin.serialization' version '$kotlinVersion'
}

graphqlGenerateClient {
    packageName = "com.example.generated"
    schemaFile = file("${project.projectDir}/mySchema.graphql")
    serializer = GraphQLSerializer.KOTLINX
}
```

</TabItem>
</Tabs>

## Generating Client using Classpath Schema

Client generation tasks require `schemaFile` to be provided. Using Gradle we can configure tasks to use local schema file,
load it from an URI or consume it directly from a classpath. See [Gradle TextResourceFactory](https://docs.gradle.org/current/dsl/org.gradle.api.resources.TextResourceFactory.html)
for additional details.

If `schema.graphql` file is provided in a `my-lib` JAR we can configure our generate client task as follows

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
  }>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
  packageName.set("com.example.generated")
  val archive = configurations["compileClasspath"].filter {
      // filter on the jar name.
      it.name.startsWith("my-lib")
  }
  schemaFile.set(resources.text.fromArchive(archive, "schema.graphql").asFile())
}
```

</TabItem>
<TabItem value="groovy">

```groovy
//build.gradle
graphqlGenerateClient {
    packageName = "com.example.generated"
    val archive = configurations["compileClasspath"].filter {
        // filter on the jar name.
        it.name.startsWith("my-lib")
    }
    schemaFile = resources.text.fromArchive(archive, "schema.graphql").asFile()
}
```

</TabItem>
</Tabs>

## Generating Test Client

GraphQL Kotlin test client code is generated based on the provided queries that will be executed against target GraphQL `schemaFile`.
Separate class is generated for each provided GraphQL query and are saved under specified `packageName`.

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
  }>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask

val graphqlGenerateTestClient by tasks.getting(GraphQLGenerateTestClientTask::class) {
  packageName.set("com.example.generated")
  schemaFile.set(file("${project.projectDir}/mySchema.graphql"))
}
```

</TabItem>
<TabItem value="groovy">

```groovy
//build.gradle
graphqlGenerateTestClient {
    packageName = "com.example.generated"
    schemaFile = file("${project.projectDir}/mySchema.graphql")
}
```

</TabItem>
</Tabs>

This will process all GraphQL queries located under `src/test/resources` and generate corresponding GraphQL Kotlin clients.
Generated classes will be automatically added to the project test compile sources.

:::info
`graphqlGenerateTestClient` cannot be configured through the `graphql` extension and has to be explicitly configured.
:::

## Minimal Client Configuration Example

Following is the minimal configuration that runs introspection query against a target GraphQL server and generates a
corresponding schema. This generated schema is subsequently used to generate GraphQL client code based on the queries
provided under `src/main/resources` directory.

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
  }>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.graphql

graphql {
  client {
    endpoint = "http://localhost:8080/graphql"
    packageName = "com.example.generated"
  }
}
```

Above configuration is equivalent to the following

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLIntrospectSchemaTask

val graphqlIntrospectSchema by tasks.getting(GraphQLIntrospectSchemaTask::class) {
  endpoint.set("http://localhost:8080/graphql")
}
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
  packageName.set("com.example.generated")
  schemaFile.set(graphqlIntrospectSchema.outputFile)
  dependsOn("graphqlIntrospectSchema")
}
```

</TabItem>
<TabItem value="groovy">

```groovy
graphql {
    client {
        endpoint = "http://localhost:8080/graphql"
        packageName = "com.example.generated"
    }
}
```

Above configuration is equivalent to the following

```groovy
// build.gradle
graphqlIntrospectSchema {
    endpoint = "http://localhost:8080/graphql"
}
graphqlGenerateClient {
    packageName = "com.example.generated"
    schemaFile = graphqlIntrospectSchema.outputFile
    dependsOn graphqlIntrospectSchema
}
```

</TabItem>
</Tabs>

## Complete Client Configuration Example

Following is a configuration example that downloads schema SDL from a target GraphQL server that is then used to generate
the GraphQL client data models using `kotlinx.serialization` that are based on the provided query.

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
}>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.config.GraphQLScalar
import com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializer
import com.expediagroup.graphql.plugin.gradle.graphql

plugins {
    kotlin("plugin.serialization") version $kotlinVersion
}

graphql {
  client {
    sdlEndpoint = "http://localhost:8080/sdl"
    packageName = "com.example.generated"
    // optional configuration
    allowDeprecatedFields = true
    customScalars = listOf(GraphQLScalar("UUID", "java.util.UUID", "com.example.UUIDScalarConverter"))
    headers = mapOf("X-Custom-Header" to "My-Custom-Header")
    queryFiles = listOf(file("${project.projectDir}/src/main/resources/queries/MyQuery.graphql"))
    serializer = GraphQLSerializer.KOTLINX
    timeout {
        connect = 10_000
        read = 30_000
    }
  }
}
```

Above configuration is equivalent to the following

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.config.GraphQLScalar
import com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializer
import com.expediagroup.graphql.plugin.gradle.config.TimeoutConfiguration
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLDownloadSDLTask
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask

plugins {
    kotlin("plugin.serialization") version $kotlinVersion
}

val graphqlDownloadSDL by tasks.getting(GraphQLDownloadSDLTask::class) {
    endpoint.set("http://localhost:8080/sdl")
    headers.put("X-Custom-Header", "My-Custom-Header")
    timeoutConfig.set(TimeoutConfiguration(connect = 10_000, read = 30_000))
}
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
    packageName.set("com.example.generated")
    schemaFile.set(graphqlDownloadSDL.outputFile)
    // optional
    allowDeprecatedFields.set(true)
    customScalars.add(GraphQLScalar("UUID", "java.util.UUID", "com.example.UUIDScalarConverter"))
    queryFiles.from("${project.projectDir}/src/main/resources/queries/MyQuery.graphql")
    serializer.set(GraphQLSerializer.KOTLINX)

    dependsOn("graphqlDownloadSDL")
}
```

</TabItem>
<TabItem value="groovy">

```groovy
// build.gradle
import com.expediagroup.graphql.plugin.gradle.config.GraphQLScalar
import com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializer

plugins {
    id 'org.jetbrains.kotlin.plugin.serialization' version '$kotlinVersion'
}

graphql {
    client {
        sdlEndpoint = "http://localhost:8080/sdl"
        packageName = "com.example.generated"
        // optional configuration
        allowDeprecatedFields = true
        customScalars = [new GraphQLScalar("UUID", "java.util.UUID", "com.example.UUIDScalarConverter")]
        headers = ["X-Custom-Header" : "My-Custom-Header"]
        queryFiles = [file("${project.projectDir}/src/main/resources/queries/MyQuery.graphql")]
        serializer = GraphQLSerializer.KOTLINX
        timeout { t ->
            t.connect = 10000
            t.read = 30000
        }
    }
}
```

Above configuration is equivalent to the following

```groovy
//build.gradle
import com.expediagroup.graphql.plugin.gradle.config.GraphQLScalar
import com.expediagroup.graphql.plugin.gradle.config.GraphQLSerializer
import com.expediagroup.graphql.plugin.gradle.config.TimeoutConfiguration

plugins {
    id 'org.jetbrains.kotlin.plugin.serialization' version '$kotlinVersion'
}

graphqlDownloadSDL {
    endpoint = "http://localhost:8080/sdl"
    headers["X-Custom-Header"] = "My-Custom-Header"
    timeoutConfig = new TimeoutConfiguration(10000, 30000)
}
graphqlGenerateClient {
    packageName = "com.example.generated"
    schemaFile = graphqlDownloadSDL.outputFile
    // optional
    allowDeprecatedFields = true
    customScalars.add(new GraphQLScalar("UUID", "java.util.UUID", "com.example.UUIDScalarConverter"))
    queryFiles.from("${project.projectDir}/src/main/resources/queries/MyQuery.graphql")
    serializer = GraphQLSerializer.KOTLINX

    dependsOn graphqlDownloadSDL
}
```

</TabItem>
</Tabs>

## Generating Multiple Clients

GraphQL Kotlin Gradle Plugin registers tasks for generation of a client queries targeting single GraphQL endpoint. You
can generate queries targeting additional endpoints by explicitly creating and configuring additional tasks.

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
  }>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLDownloadSDLTask
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask

val graphqlDownloadSDL by tasks.getting(GraphQLDownloadSDLTask::class) {
    endpoint.set("http://localhost:8080/sdl")
}
val graphqlGenerateClient by tasks.getting(GraphQLGenerateClientTask::class) {
    packageName.set("com.example.generated.first")
    schemaFile.set(graphqlDownloadSDL.outputFile)
    queryFiles.from("${project.projectDir}/src/main/resources/queries/MyFirstQuery.graphql")
    dependsOn("graphqlDownloadSDL")
}

val graphqlDownloadOtherSDL by tasks.creating(GraphQLDownloadSDLTask::class) {
    endpoint.set("http://localhost:8081/sdl")
}
val graphqlGenerateOtherClient by tasks.creating(GraphQLGenerateClientTask::class) {
    packageName.set("com.example.generated.second")
    schemaFile.set(graphqlDownloadOtherSDL.outputFile)
    queryFiles.from("${project.projectDir}/src/main/resources/queries/MySecondQuery.graphql")
    dependsOn("graphqlDownloadOtherSDL")
}
```

</TabItem>
<TabItem value="groovy">

```groovy
//build.gradle
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLDownloadSDLTask
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateClientTask

graphqlDownloadSDL {
    endpoint = "http://localhost:8080/sdl"
}
graphqlGenerateClient {
    packageName = "com.example.generated.first"
    schemaFile = graphqlDownloadSDL.outputFile
    queryFiles.from("${project.projectDir}/src/main/resources/queries/MyFirstQuery.graphql")

    dependsOn graphqlDownloadSDL
}

task graphqlDownloadOtherSDL(type: GraphQLDownloadSDLTask) {
    endpoint = "http://localhost:8081/sdl"
}
task graphqlGenerateOtherClient(type: GraphQLGenerateClientTask) {
    packageName = "com.other.generated.second"
    schemaFile = graphqlDownloadOtherSDL.outputFile
    queryFiles.from("${project.projectDir}/src/main/resources/queries/MySecondQuery.graphql")

    dependsOn graphqlDownloadOtherSDL
}
```

</TabItem>
</Tabs>

## Generating SDL Example

GraphQL schema can be generated directly from your source code using reflections. `graphqlGenerateSDL` will scan your
classpath looking for classes implementing `Query`, `Mutation` and `Subscription` marker interfaces and then generates the
corresponding GraphQL schema using `graphql-kotlin-schema-generator` and default `NoopSchemaGeneratorHooks`. In order to
limit the amount of packages to scan, this task requires users to provide a list of `packages` that can contain GraphQL
types.

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
  }>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.graphql

graphql {
  schema {
    packages = listOf("com.example")
  }
}
```

Above configuration is equivalent to the following task definition

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateSDLTask

val graphqlGenerateSDL by tasks.getting(GraphQLGenerateSDLTask::class) {
    packages.set(listOf("com.example"))
}
```

</TabItem>
<TabItem value="groovy">

```groovy
// build.gradle
graphql {
  schema {
    packages = ["com.example"]
  }
}
```

Above configuration is equivalent to the following task definition

```groovy
//build.gradle
graphqlGenerateSDL {
    packages = ["com.example"]
}
```

</TabItem>
</Tabs>

:::info
This task does not automatically configure itself to be part of your build lifecycle. You will need to explicitly
invoke it OR configure it as a dependency of some other task.
:::

## Generating SDL with Custom Hooks Provider Example

Plugin will default to use `NoopSchemaGeneratorHooks` to generate target GraphQL schema. If your project uses custom hooks
or needs to generate the federated GraphQL schema, you will need to provide an instance of `SchemaGeneratorHooksProvider`
service provider that will be used to create an instance of your custom hooks.

`graphqlGenerateSDL` utilizes [ServiceLoader](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.html)
mechanism to dynamically load available `SchemaGeneratorHooksProvider` service providers from the classpath. Service provider
can be provided as part of your project, included in one of your project dependencies or through explicitly provided artifact.
See [Schema Generator Hooks Provider](./hooks-provider.mdx) for additional details on how to create custom hooks service provider.
Configuration below shows how to configure GraphQL Kotlin plugin with explicitly provided artifact to generate federated
GraphQL schema.

<Tabs
  defaultValue="kotlin"
  values={[
    { label: 'Kotlin', value: 'kotlin' },
    { label: 'Groovy', value: 'groovy' }
  ]
  }>

<TabItem value="kotlin">

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.graphql

graphql {
  schema {
    packages = listOf("com.example")
  }
}

dependencies {
    graphqlSDL("com.expediagroup:graphql-kotlin-federated-hooks-provider:$graphQLKotlinVersion")
}
```

Above configuration is equivalent to the following task definition

```kotlin
// build.gradle.kts
import com.expediagroup.graphql.plugin.gradle.tasks.GraphQLGenerateSDLTask

val graphqlGenerateSDL by tasks.getting(GraphQLGenerateSDLTask::class) {
    packages.set(listOf("com.example"))
}

dependencies {
    graphqlSDL("com.expediagroup:graphql-kotlin-federated-hooks-provider:$graphQLKotlinVersion")
}
```

</TabItem>
<TabItem value="groovy">

```groovy
// build.gradle
graphql {
  schema {
    packages = ["com.example"]
  }
}

dependencies {
    graphqlSDL "com.expediagroup:graphql-kotlin-federated-hooks-provider:$DEFAULT_PLUGIN_VERSION"
}
```

Above configuration is equivalent to the following task definition

```groovy
//build.gradle
graphqlGenerateSDL {
    packages = ["com.example"]
}

dependencies {
    graphqlSDL "com.expediagroup:graphql-kotlin-federated-hooks-provider:$DEFAULT_PLUGIN_VERSION"
}
```

</TabItem>
</Tabs>

:::info
This task does not automatically configure itself to be part of your build lifecycle. You will need to explicitly
invoke it OR configure it as a dependency of some other task.
:::
